package com.pubinfo.passbook.common.service.ruler.impl;

import com.pubinfo.passbook.common.entity.TPassbook;
import com.pubinfo.passbook.common.model.ruler.PayInformation;
import com.pubinfo.passbook.common.model.ruler.PersonInformation;
import com.pubinfo.passbook.common.service.master.TPassbookService;
import com.pubinfo.passbook.common.service.master.TRabbitmqPersonService;
import com.pubinfo.passbook.common.service.ruler.CheckService;
import com.pubinfo.passbook.common.service.ruler.InformationService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class InformationServiceImpl implements InformationService {
  
  @Autowired
  TPassbookService passbookService;
  @Autowired
  TRabbitmqPersonService personService;
  @Autowired
  CheckService checkService;
  
  @Override
  public PayInformation GetInformationFromPassbook(String id) {
    List<String> idList = new ArrayList<>();
    idList.add(id);
    TPassbook passbook = passbookService.getPassbookById(idList).get(0);
    String xml = passbook.getEinvoiceXml();
    Document document = null;
    try {
      document = DocumentHelper.parseText(xml);
    } catch (DocumentException e) {
      log.error("解析票据数据失败", e);
    }
    Element root = document.getRootElement();
    PayInformation payInformation = new PayInformation(root);
    payInformation.setEInvoiceId(id);
    payInformation.setId(passbook.getId());
//        if (StringUtils.isNotBlank(payInformation.getFundPayAmountInfo())) {
//            String info = payInformation.getFundPayAmountInfo();
//            String poolingFundPaymentStr = info.substring(info.indexOf(":") + 1, info.indexOf(".") + 3).trim();
//            if (StringUtils.isNotBlank(poolingFundPaymentStr)) {
//                payInformation.setPoolingFundPayment(new BigDecimal(poolingFundPaymentStr));
//            }
//
//            String startPayStr = info.substring(info.lastIndexOf(":") + 1, info.lastIndexOf(".") + 3).trim();
//            if (StringUtils.isNotBlank(poolingFundPaymentStr)) {
//                payInformation.setStartPay(new BigDecimal(startPayStr));
//
//            }
//        }
    return payInformation;
  }
  
  @Override
  public List<PayInformation> listInformationFromPassbook(List<String> ids) {
    List<PayInformation> payInformations = new ArrayList<>();
    if (CollectionUtils.isEmpty(ids)) {
      return payInformations;
    }
    ids.stream().forEach(id -> {
      PayInformation payInformation = GetInformationFromPassbook(id);
      payInformations.add(payInformation);
    });
    return payInformations;
  }
  
  @SneakyThrows
  public static <T> T convertListValueToObjectValue(List<T> responses, Class<T> clazz) {
    Object object = clazz.newInstance();
    Class<?> aClass = object.getClass();
    Field[] declaredFields = aClass.getDeclaredFields();
    for (Field declaredField : declaredFields) {
      if ("java.math.BigDecimal".equals(declaredField.getType().getName())) {
        declaredField.setAccessible(true);
        for (Object row : responses) {
          Field[] rowFields = row.getClass().getDeclaredFields();
          for (Field rowField : rowFields) {
            if ("java.math.BigDecimal".equals(rowField.getType().getName()) && rowField.getName().equals(declaredField.getName())) {
              rowField.setAccessible(true);
              
              BigDecimal tem = (BigDecimal) rowField.get(row);
              BigDecimal dst = (BigDecimal) declaredField.get(object);
              declaredField.set(object, tem.add(dst));
            }
            
          }
        }
      }
    }
    return (T) object;
  }
  
  @Override
  public PayInformation informationFromPassbook(List<String> ids) {
    List<PayInformation> payInformationList = listInformationFromPassbook(ids);
    PayInformation payInformation =convertListValueToObjectValue(payInformationList, PayInformation.class);
    //List<Details> detailsList =payInformationList.stream()
    return payInformation;
  }
  
  @Override
  public BigDecimal getPassbookSum(List<String> ids) {
    BigDecimal sum = new BigDecimal(0);
    List<PayInformation> payInformationList = listInformationFromPassbook(ids);
    if (!CollectionUtils.isEmpty(payInformationList)) {
      for (PayInformation payInformation : payInformationList) {
        
        sum = sum.add(payInformation.getTotalAmount());
      }
    }
    return sum;
  }
  
  @Override
  public PersonInformation GetPersonInformationFrom4A(String acct) {
    return new PersonInformation(personService.selectByAcctId(acct));
  }
  
  @Override
  public BigDecimal getSumAmountSelfByType(String passbookId, Map<String, BigDecimal> types) {
    //根据passbookId获取票据的xml
    List<String> idList = new ArrayList<>();
    idList.add(passbookId);
    TPassbook passbook = passbookService.getPassbookById(idList).get(0);
    String xml = passbook.getEinvoiceXml();
    Document document = null;
    try {
      document = DocumentHelper.parseText(xml);
    } catch (DocumentException e) {
      log.error("解析票据数据失败", e);
    }
    //自费合计金额
    BigDecimal sum = new BigDecimal(0);
  
    List nodes = document.getRootElement().element("EInvoiceData").element("AuxDetails").elements("AuxItem");
    if (!CollectionUtils.isEmpty(nodes)) {
      for (Iterator it = nodes.iterator(); it.hasNext(); ) {
        Element element = (Element) it.next();
        String auxItemType = null;
      
        String itemNameStr;
        String itemAmountStr;
      
        try {
          auxItemType = element.element("AuxItemType").getText();
        } catch (NullPointerException e) {
          log.error("票据错误");
          continue;
        }
        for (String type : types.keySet()) {
          if (auxItemType.equals(type)) {
            sum = sum.add(new BigDecimal(element.element("AuxItemAmountSelf").getText()).multiply(types.get(type)));
            //直接break防止类型有重复
            break;
          }
        }
      }
    }
  
    return sum;
  }
  
  @Override
  public BigDecimal getAmountByCostName(String passbookId) {
    //根据passbookId获取票据的xml
    List<String> idList = new ArrayList<>();
    idList.add(passbookId);
    TPassbook passbook = passbookService.getPassbookById(idList).get(0);
    String xml = passbook.getEinvoiceXml();
    Document document = null;
    try {
      document = DocumentHelper.parseText(xml);
    } catch (DocumentException e) {
      log.error("解析票据数据失败", e);
    }
    //自费合计金额
    BigDecimal sum = new BigDecimal(0);
    List auxItems;
    Boolean haveVerticalPlate = checkService.haveVerticalPlate(idList);
    if (haveVerticalPlate) {
      auxItems = document.getRootElement().element("EInvoiceData").element("Details").elements("Item");
    } else {
      auxItems = document.getRootElement().element("EInvoiceData").element("AuxDetails").elements("AuxItem");
    }
  
    if (!CollectionUtils.isEmpty(auxItems)) {
      for (Iterator it = auxItems.iterator(); it.hasNext(); ) {
        Element auxItem = (Element) it.next();
        //   Element auxItem = null;
        try {
          //    auxItem = element.element("AuxItem");
          if (auxItem != null) {
            String itemNameStr;
            String itemAmountStr;
            if (haveVerticalPlate) {
              itemNameStr = "ItemName";
              itemAmountStr = "ItemAmount";
            } else {
            
              itemNameStr = "AuxItemRelatedName";
              itemAmountStr = "AuxItemAmount";
            }
            //ItemAmount
            Element itemNameEL = auxItem.element(itemNameStr);
            if (itemNameEL != null) {
              if ("诊察费".equals(itemNameEL.getText())) {
                sum = sum.add(new BigDecimal(auxItem.element(itemAmountStr).getText()));
              }
            }
            //AuxItemRelatedName
          
          }
        
        } catch (NullPointerException e) {
          log.error("票据错误");
          continue;
        }
      }
    }
  
    return sum;
  }
}
